import { Component, OnInit, Input, Output, EventEmitter, ViewChild, ElementRef, SimpleChanges } from '@angular/core';
import { GanttService } from '../../../services/gantt-chart/gantt.service';
import { PREVTYPE } from '../../../services/gantt-chart/gantt.config';
import * as moment from 'moment';

import { NzModalService } from 'ng-zorro-antd';
@Component({
  selector: 'app-gantt-box',
  templateUrl: './gantt-box.component.html',
  styleUrls: ['./gantt-box.component.scss']
})
export class GanttBoxComponent implements OnInit {
  @ViewChild('myCanvas', { static: false }) public canvasRef: ElementRef;
  @Input() public showTask: any;
  @Input() public canvasInfo: any;
  @Input() public rightPanelWidth: any;
  // @Input() allTasks :any;
  private isViewInit = false;

  public weeksArry: any = [];
  public weeksWidth: any;
  public defaultWeek: any = ['日', '一', '二', '三', '四', '五', '六'];
  public calendarWidth: number;
  public canvasWidth = 800;
  public loadingShow = true;

  public boxScrollLeft = 0;

  // deviationY: number = 10;
  public lineHeight = 26;
  public actualLineHeight = 10;

  public color = 'rgba(65,159,229, 0.2)';
  public keyColor = 'rgba(255, 128, 128, 0.2)';

  public Actualcolor = '#419fe8';
  public ActualkeyColor = '#ff8080';



  public constructor(public ganttService: GanttService) {

  }

  public ngOnInit() {

  }

  public ngOnChanges(changes: { [propName: string]: SimpleChanges }) {
    // let canvasInfo = this.ganttService.canvasInfo;
    // console.log(canvasInfo)
    this.weeksArry = this.ganttService.weeksArry;
    // 右边容器宽度
    let ganttBoxWidth = this.rightPanelWidth;
    // 日历宽度
    let calendarWidth = this.ganttService.calenderWidth;
    this.loadingShow = true;
    if (ganttBoxWidth >= calendarWidth) {
      this.calendarWidth = ganttBoxWidth;
      this.loadingShow = true;
    } else {
      this.calendarWidth = calendarWidth;
      this.loadingShow = true;
    }
    setTimeout(() => {
      this.loadingShow = false;
      this.drawCanvas();
    }, 200);
  }

  public boxScroll(e) {
    this.boxScrollLeft = e.target.scrollLeft;
    this.drawCanvas();
  }

  // 清空画布
  public cleanCanvas = () => {
    let ctx: CanvasRenderingContext2D =
      this.canvasRef.nativeElement.getContext('2d');
    ctx.clearRect(0, 0, this.rightPanelWidth, this.ganttService.canvasHeight);
  }

  public drawCanvas() {
    console.log('start---drawCanvas');
    let ctx: CanvasRenderingContext2D =
      this.canvasRef.nativeElement.getContext('2d');
    // Draw the clip path that will mask everything else
    // that we'll draw later.
    ctx.clearRect(0, 0, this.rightPanelWidth, this.ganttService.canvasHeight);
    // 绘制日历
    let canvasInfo = this.ganttService.canvasInfo;
    let actualCanvasInfo = this.ganttService.actualCanvasInfo;
    let exceptCanvasInfo = this.ganttService.exceptCanvasInfo;
    if (canvasInfo && canvasInfo.length > 0) {
      // 绘制横道图
      this.drawExceptArea(ctx, exceptCanvasInfo);
      this.drawTasks(ctx, canvasInfo, false);
    }
    if (actualCanvasInfo && actualCanvasInfo.length > 0) {
      this.drawTasks(ctx, actualCanvasInfo, true);
    }
  }

  // 绘制多段线
  // drawLines(ctx) {
  //   // 设置线条的颜色
  //   ctx.strokeStyle = 'red';
  //   // 设置线条的宽度
  //   ctx.lineWidth = 1;

  //   // 绘制直线
  //   ctx.beginPath();
  //   // 起点
  //   ctx.moveTo(200, 200);
  //   // 终点
  //   ctx.lineTo(500, 200);
  //   ctx.closePath();
  //   ctx.stroke();
  // }

  public drawExceptArea(ctx, exceptCanvasInfo) {
    for (let i = 0; i < exceptCanvasInfo.length; i++) {
      const element = exceptCanvasInfo[i];
      let fromX = exceptCanvasInfo[i].positionX - this.boxScrollLeft;
      let width = exceptCanvasInfo[i].width;
      ctx.beginPath();
      ctx.fillStyle = '#f5f5f5';
      ctx.fillRect(fromX, 0, width, this.ganttService.canvasHeight);
      ctx.fill();
      ctx.closePath();
    }
  }

  public drawTasks(ctx, canvasInfo: any, isActual?: boolean) {
    let canvasWidth = this.rightPanelWidth;
    let allTasks = this.ganttService.allTasks;
    let hideTasksId = this.ganttService.hideTasksId;
    for (let i = 0; i < this.showTask.length; i++) {
      let index = this.showTask[i].id - 1;
      let mileStoneText = moment(this.showTask[i].endDate).format('DD/MM');
      let fromX = canvasInfo[index].positionX - this.boxScrollLeft;
      let fromY = canvasInfo[index].positionY;
      let width = canvasInfo[index].width;
      let isKey = canvasInfo[index].isKey;
      let type = canvasInfo[index].type;

      ctx.beginPath();
      if (type == 'parentType') {
        if (!isActual) {
          // 父任务
          let toX = fromX + width;
          let toY = fromY;
          this.drawSenior(ctx, fromX, fromY, toX, toY);
        }
      } else if (type == 'milepost') {
        // 里程碑
        this.drawPolygon(ctx, {
          x: fromX,
          y: fromY + 5,
          num: 4,
          r: 6,
          width: 1,
          fillStyle: '#0e77ca'
        });
        this.drawText(ctx, mileStoneText, fromX + 5, fromY + 5, 12);
      } else {
        // 普通任务

        if (isActual) {
          ctx.fillStyle = isKey ? this.ActualkeyColor : this.Actualcolor;
          ctx.fillRect(fromX, fromY, width, this.actualLineHeight);
        } else {
          ctx.fillStyle = isKey ? this.keyColor : this.color;
          ctx.fillRect(fromX, fromY, width, this.lineHeight);
        }

        ctx.fill();
      }
      ctx.closePath();

      // 选中任务
      if (this.showTask[i].IsSelected && !isActual) {
        this.drawLine(ctx, 0, fromY - 5, canvasWidth, fromY - 5, 1, '#ccc');
        this.drawLine(ctx, 0, fromY + 31, canvasWidth, fromY + 31, 1, '#ccc');
      }

      // 前置任务到自己的箭头
      if (this.showTask[i].truePrevTaskID && !isActual) {
        let currentTask = this.showTask[i];
        let relations = currentTask.prevRelation;
        let shortLine = 8;
        if (relations.length > 0) {
          relations.forEach((relation) => {
            if (!relation.isDelete) {
              let number = relation.relation;
              let prevId = relation.prevId;
              let prevX = canvasInfo[prevId - 1].positionX - this.boxScrollLeft;
              let prevY = canvasInfo[prevId - 1].positionY;
              let prevIsKey = canvasInfo[prevId - 1].isKey;
              let prevWith = canvasInfo[prevId - 1].width;
              let isKey = canvasInfo[index].isKey;
              let conectColor = isActual ? '#419fe8' : this.color;
              if (prevIsKey && isKey) {
                conectColor = isActual ? '#e74b8f' : this.keyColor;
              }

              let helfLineHeight = this.lineHeight / 2;
              if (hideTasksId.indexOf(prevId) === -1) {
                if (number === PREVTYPE.FS) {
                  // 完成-开始(FS)
                  let points = [
                    { x: prevX + prevWith, y: prevY + helfLineHeight },
                    { x: fromX, y: prevY + helfLineHeight }
                  ];
                  this.drawBrokenLine(ctx, points, 1, conectColor, isActual);
                  this.drawArrow(ctx, fromX, prevY + helfLineHeight, fromX, fromY);
                }

                if (number === PREVTYPE.SS) {
                  // 开始-开始(SS)
                  let points = [
                    { x: prevX, y: prevY + helfLineHeight },
                    { x: prevX - shortLine, y: prevY + helfLineHeight },
                    { x: prevX - shortLine, y: fromY + helfLineHeight }
                  ];
                  this.drawBrokenLine(ctx, points, 1, conectColor, isActual);
                  this.drawArrow(ctx, prevX - shortLine, fromY + helfLineHeight, fromX, fromY + helfLineHeight);
                }

                if (number === PREVTYPE.FF) {
                  // 完成-完成(FF)
                  let points = [
                    { x: prevX + prevWith, y: prevY + helfLineHeight },
                    { x: fromX + width + shortLine, y: prevY + helfLineHeight },
                    { x: fromX + width + shortLine, y: fromY + helfLineHeight }
                  ];
                  this.drawBrokenLine(ctx, points, 1, conectColor, isActual);
                  this.drawArrow(ctx, fromX + width + shortLine, fromY + helfLineHeight, fromX + width, fromY + helfLineHeight);
                }

                if (number === PREVTYPE.SF) {
                  // 开始-完成(SF)
                  let points = [
                    { x: prevX, y: prevY + helfLineHeight },
                    { x: prevX - shortLine, y: prevY + helfLineHeight },
                    { x: prevX - shortLine, y: prevY + this.lineHeight + 5 },
                    { x: fromX + width + shortLine, y: prevY + this.lineHeight + 5 },
                    { x: fromX + width + shortLine, y: fromY + helfLineHeight }
                  ];
                  this.drawBrokenLine(ctx, points, 1, conectColor, isActual);
                  this.drawArrow(ctx, fromX + width + shortLine, fromY + helfLineHeight, fromX + width, fromY + helfLineHeight);
                }
              }
            }
          });
        }
      }
    }
  }

  public drawBrokenLine(ctx, points: any[], width?: number, color?: string, isActual?: boolean) {
    // 绘制直线
    ctx.beginPath();
    ctx.strokeStyle = color;
    // 设置线条的宽度
    ctx.lineWidth = width ? width : 1;

    // 起点
    ctx.moveTo(points[0].x, points[0].y);
    // 路径
    for (let i = 0; i < points.length; i++) {
      ctx.lineTo(points[i].x, points[i].y);
    }
    ctx.stroke();
  }

  public drawLine(ctx, fromX, fromY, toX, toY, width, color) {
    color = typeof (color) != 'undefined' ? color : '#000';
    ctx.save();
    ctx.beginPath();
    // ctx.translate(0.5, 0.5);
    ctx.strokeStyle = color;
    ctx.lineWidth = width;
    ctx.moveTo(fromX - 0.5, fromY - 0.5);
    ctx.lineTo(toX - 0.5, toY - 0.5);
    // ctx.moveTo(fromX, fromY);
    // ctx.lineTo(toX, toY);
    ctx.stroke();
    ctx.restore();
  }

  /*
  绘制箭头：
  ctx：Canvas绘图环境
  fromX, fromY：起点坐标（也可以换成p1，只不过它是一个数组）
  toX, toY：终点坐标 (也可以换成p2，只不过它是一个数组)
  theta：三角斜边一直线夹角
  headlen：三角斜边长度
  width：箭头线宽度
  color：箭头颜色
  */
  public drawArrow(ctx, fromX, fromY, toX, toY, theta?: number, headlen?: number, width?: number, color?: string) {
    theta = theta ? theta : 30;
    headlen = headlen ? headlen : 5;
    width = width ? width : 1;

    // 计算各角度和对应的p2,p3坐标
    let angle = Math.atan2(fromY - toY, fromX - toX) * 180 / Math.PI,
      angle1 = (angle + theta) * Math.PI / 180,
      angle2 = (angle - theta) * Math.PI / 180,
      topX = headlen * Math.cos(angle1),
      topY = headlen * Math.sin(angle1),
      botX = headlen * Math.cos(angle2),
      botY = headlen * Math.sin(angle2);

    ctx.save();
    ctx.beginPath();

    let arrowX = fromX - topX,
      arrowY = fromY - topY;

    ctx.moveTo(arrowX, arrowY);
    ctx.moveTo(fromX, fromY);
    ctx.lineTo(toX, toY);

    arrowX = toX + topX;
    arrowY = toY + topY;
    ctx.moveTo(arrowX, arrowY);
    ctx.lineTo(toX, toY);
    arrowX = toX + botX;
    arrowY = toY + botY;
    ctx.lineTo(toX, toY);
    arrowX = toX + botX;
    arrowY = toY + botY;
    ctx.lineTo(arrowX, arrowY);
    ctx.lineWidth = width;
    ctx.stroke();
    ctx.restore();
    ctx.closePath();
  }

  /*
  * formX, fromY
  * toX, toY
  */
  public drawSenior(ctx, fromX, fromY, toX, toY) {
    let width = 1;
    let color = '#707070';
    this.drawLine(ctx, fromX, fromY + 10, fromX, toY, width, color);
    this.drawLine(ctx, fromX, fromY, toX, toY, width, color);
    this.drawLine(ctx, toX, toY, toX, toY + 10, width, color);
  }

  /*
  绘制文本
  */
  public drawText(ctx, text: string, x: number, y: number, fontSize) {
    ctx.font = `${fontSize}px sans-serif`;
    ctx.textBaseline = 'middle';
    ctx.fillText(text, x, y);
  }

  /*
  绘制多边形
  x：中心点x坐标
  y：中心点y坐标
  num：多边形边数
  r：多边形半径
  width：线条宽度
  */
  public drawPolygon(ctx, conf) {
    let x = conf && conf.x || 0;  //中心点x坐标
    let y = conf && conf.y || 0;  //中心点y坐标
    let num = conf && conf.num || 3;   //图形边的个数
    let r = conf && conf.r || 6;   //图形的半径
    let width = conf && conf.width || 1;
    let strokeStyle = conf && conf.strokeStyle;
    let fillStyle = conf && conf.fillStyle;
    //开始路径
    ctx.beginPath();
    let startX = x + r * Math.cos(2 * Math.PI * 0 / num);
    let startY = y + r * Math.sin(2 * Math.PI * 0 / num);
    ctx.moveTo(startX, startY);
    for (let i = 1; i <= num; i++) {
      let newX = x + r * Math.cos(2 * Math.PI * i / num);
      let newY = y + r * Math.sin(2 * Math.PI * i / num);
      ctx.lineTo(newX, newY);
    }
    ctx.closePath();
    //路径闭合
    if (strokeStyle) {
      ctx.strokeStyle = strokeStyle;
      ctx.lineWidth = width;
      ctx.lineJoin = 'round';
      ctx.stroke();
    }
    if (fillStyle) {
      ctx.fillStyle = fillStyle;
      ctx.fill();
    }
  }

}
